package top.cardone.log.appender;

import com.google.common.collect.Maps;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.core.Filter;
import org.apache.logging.log4j.core.Layout;
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.appender.AbstractAppender;
import org.apache.logging.log4j.core.config.Property;
import org.apache.logging.log4j.core.config.plugins.Plugin;
import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
import org.apache.logging.log4j.core.config.plugins.PluginElement;
import org.apache.logging.log4j.core.config.plugins.PluginFactory;
import org.apache.logging.log4j.core.layout.PatternLayout;
import top.cardone.context.ApplicationContextHolder;
import top.cardone.log.action.InsertOperateLogByEventListenerAction;

import java.io.Serializable;
import java.util.Map;

@Plugin(name = "Database", category = "Core", elementType = "appender", printObject = true)
public class DatabaseAppender extends AbstractAppender {
    protected String collectionName;

    protected DatabaseAppender(String name, Filter filter, Layout<? extends Serializable> layout, boolean ignoreExceptions, Property[] properties, String collectionName) {
        super(name, filter, layout, ignoreExceptions, properties);

        this.collectionName = collectionName;
    }

    @Override
    public void append(LogEvent event) {
        Map<String, Object> insert = Maps.newHashMap();

        insert.put("collectionName", this.collectionName);
        insert.put("levelName", event.getLevel() == null ? null : event.getLevel().name());
        insert.put("spring_application_name", ApplicationContextHolder.getApplicationContext().getEnvironment().getProperty("spring.application.name",String.class,""));
        insert.put("spring_profiles_active", ApplicationContextHolder.getApplicationContext().getEnvironment().getProperty("spring.profiles.active",String.class,""));
//        insert.put("contextData", event.getContextData());
        insert.put("message", event.getMessage() == null ? null : event.getMessage().getFormattedMessage());
//        insert.put("nanoTime", event.getNanoTime());
        insert.put("threadId", event.getThreadId());
//        insert.put("loggerFqcn", event.getLoggerFqcn());
        insert.put("loggerName", event.getLoggerName());
        insert.put("threadName", event.getThreadName());
        insert.put("threadPriority", event.getThreadPriority());
//        insert.put("thrown", event.getThrown());
        insert.put("timeMillis", event.getTimeMillis());

        ApplicationContextHolder.getBean(InsertOperateLogByEventListenerAction.class).action(insert);
    }

    @PluginFactory
    public static DatabaseAppender createAppender(@PluginAttribute("name") String name,
                                                  @PluginElement("Filter") final Filter filter,
                                                  @PluginElement("Layout") Layout<? extends Serializable> layout,
                                                  @PluginAttribute("ignoreExceptions") boolean ignoreExceptions,
                                                  @PluginAttribute("collectionName") String collectionName) {
        if (StringUtils.isBlank(name)) {
            LOGGER.error("No name provided for DatabaseAppender");

            return null;
        }

        if (StringUtils.isBlank(collectionName)) {
            LOGGER.error("No collectionName provided for DatabaseAppender");

            return null;
        }

        if (layout == null) {
            layout = PatternLayout.createDefaultLayout();
        }

        return new DatabaseAppender(name, filter, layout, ignoreExceptions, null, collectionName);
    }
}
